﻿using System.Runtime.InteropServices;
using System.Collections.Generic;
using MSI = Pahvant.MSI;
using System.Linq;
using System.Text;
using log4net;
using System;

namespace Updater.Common
{
    public class MSIInstaller
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(MSIInstaller));

        static MSIInstaller()
        {
            MSI.Installer.SetExternalUI(new MSI.Installer.UIHandlerDelegate(UIHandler), 5, IntPtr.Zero); //this);
        }
      
        /// <summary>
        /// Installs the MSI file which is pointed to, into the destination path, 
        /// if there is already an installation this is overwritten, this currently only works for websites.
        /// </summary>
        /// <param name="PathToMSI"></param>
        /// <param name="DestinationPath"></param>
        public int InstallMsiTo(string PathToMSI, string DestinationPath, Dictionary<string,string> parameters)
        {
            try
            {
                //TODO this should be different from depending on a wheter it is a web or winforms document
                // which is beeing installed.
                //string INSTALLCOMMANDLINE = "TARGETDIR=" + DestinationPath;

                //string INSTALLCOMMANDLINEV = "TARGETVDIR=" + DestinationPath;

            //    string REMOVECOMMANDLINE = "REMOVE=ALL";

                string commandLine = string.Empty;
                if (!string.IsNullOrEmpty(DestinationPath))
                {
                    commandLine = "TARGETVDIR=" + DestinationPath + "REINSTALL=ALL REINSTALLMODE=vemus";
                }
                foreach (var parameter in parameters)
                {
                    commandLine += string.Format(" {0}=\"{1}\" ", parameter.Key, parameter.Value);
                }


                //TARGETVDIR
                

                // Enables log
                MSI.Installer.EnableLog(Pahvant.MSI.InstallLogMode.ExtraDebug, Properties.Settings.Default.MSIInstallerLogPath, Pahvant.MSI.InstallLogAttributes.Append);
                
                // sets the installation to silent with no user interaction.

                new MSI.Package(PathToMSI).Verify();

                // Get Install date of previous version
                // string test = MSI.Installer.GetProductInfo("{8E9FA764-0646-4326-AF6C-231708D61405}", "InstallDate");

                new MSI.Package(PathToMSI).Install(commandLine);
                                
                return 0;
            }
            catch (Exception exception)
            {
                log.Error("Failed to install MSI package", exception);
                return -1;
            }
        }

        public int InstallMsiTo(string PathToMSI, string DestinationPath)
        {
            return InstallMsiTo(PathToMSI, DestinationPath, new Dictionary<string, string>());
        }
        
        public static int UIHandler(IntPtr context, int messageType, string message)
        {
            MSI.InstallMessage kind = (MSI.InstallMessage) (0xFF000000 & messageType);
            int result = -1;
            switch (kind)
            {
                case MSI.InstallMessage.ActionData:
                    result = (int) MSI.Installer.ControlIds.IDOK;
                    break;
                case MSI.InstallMessage.ActionStart:
                    result = (int) MSI.Installer.ControlIds.IDOK;
                    break;
                case MSI.InstallMessage.Progress:
                    result = (int) MSI.Installer.ControlIds.IDOK;
                    break;

                case MSI.InstallMessage.CommonData:
                    break;
                case MSI.InstallMessage.Error:
                    break;
                case MSI.InstallMessage.FatalExit:
                    break;
                case MSI.InstallMessage.FilesInUse:
                    break;
                case MSI.InstallMessage.Info:
                    break;
                case MSI.InstallMessage.Initialize:
                    break;
                case MSI.InstallMessage.OutOfDiskSpace:
                    break;
                case MSI.InstallMessage.ResolveSource:
                    break;
                case MSI.InstallMessage.ShowDialog:
                    break;
                case MSI.InstallMessage.Terminate:
                    break;
                case MSI.InstallMessage.User:
                    break;
                case MSI.InstallMessage.Warning:
                    break;

                default:
                    break;
            }
            return result;
        }
    }
}

/*
   C:\Projects\UpdaterService\Updater.Service.Setup\Debug>msiexec /i setup.msi /qb /l* out.txt


   C:\Projects\UpdaterService\Updater.Service.Setup\Debug>msiexec /i "SetupUpdaterService.msi" /q TARGETDIR="C:\test"*/